//! # mapper - Midi Note 的映射模块
//!
//! 映射器用于将 MIDI 事件映射到实际的功能上。
//!
//! 只需要实现 [`MidiMapper`] Trait，即可实现一个映射器。
//!
//! 另外需要注意的是，映射器需要加上宏 [`async_trait`]。
//!
//! 如果想要统一构造，可以在 [`create_mapper`] 函数中添加初始化逻辑。
//!
//! ## 示例
//!
//! ```
//! pub struct MyMapper { /* 你的实现 */ }
//!
//! impl MidiMapper for EmptyMapper { /* 你的实现 */ }
//! ```

pub mod empty_mapper;
pub mod key_mapper;

use std::time::Duration;

use async_trait::async_trait;
use midly::{num::u4, MetaMessage, MidiMessage};
use serde_json::Value;

use self::{empty_mapper::EmptyMapper, key_mapper::KeyMapper};

/// Midi 映射器
#[async_trait]
#[allow(unused_variables)]
pub trait MidiMapper: Send {
    /// 启动
    async fn start(&mut self) {}
    /// 接收元信息
    async fn on_meta(&mut self, track: usize, meta: &MetaMessage) {}
    /// 接收 Midi 信息
    async fn on_midi(&mut self, track: usize, channel: u4, message: MidiMessage) {}
    /// 接收 SysEx 信息
    async fn on_sys_ex(&mut self, track: usize, data: &[u8]) {}
    /// 接收 Escape 信息
    async fn on_escape(&mut self, track: usize, data: &[u8]) {}
    /// 结束
    async fn finish(&mut self, duration: Duration) {}
}

/// 创建映射器错误
#[derive(Debug, Clone)]
pub enum CreateMapperError {
    /// 未知的映射器
    UnknownMapper(String),
    /// 非法的规则
    IllegalRule(String),
}

/// 创建映射器
///
/// # 参数
///
/// * `name` - 映射器名称
/// * `rule` - 映射规则
///
/// # 返回值
///
/// * `Ok(Box<dyn MidiMapper>)` - 映射器
/// * `Err(CreateMapperError)` - 创建映射器错误
///
/// # 示例
///
/// ```
/// let mapper = create_mapper("keymapper", json!({ /* 你的规则 */ }));
/// ```
pub fn create_mapper(name: &str, rule: Value) -> Result<Box<dyn MidiMapper>, CreateMapperError> {
    match name.to_lowercase().as_str() {
        "emptymapper" | "defaultmapper" => Ok(Box::new(EmptyMapper {})),
        "keymapper" => {
            let mapper = KeyMapper::from_rule(rule)?;
            Ok(Box::new(mapper))
        }
        _ => Err(CreateMapperError::UnknownMapper(name.to_owned())),
    }
}
